package org.example.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.NetSocket;
import io.vertx.mqtt.MqttServer;
import org.example.domain.TakePosition;
import org.example.domian.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class MarketService {
    public static final Map<Integer, OrderBook> stocks = new HashMap<>();
    public static List<Sell> msgList = Lists.newArrayList();
    public static List<Three> sellMsgList = Lists.newArrayList();

    public static List<Three> jsonToThree(String json) {
        JSONArray jsonArray = new JSONArray(json);
        ArrayList<Three> threes = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Three three = new Three();
            three.setId(jsonObject.getInt("id"));
            three.setBuyId(jsonObject.getInt("buyId"));
            three.setSellId(jsonObject.getInt("sellId"));
            three.setBuyNum(jsonObject.getInt("buyNum"));
            three.setAveragePrice(jsonObject.getDouble("averagePrice"));
            three.setSellPrice(jsonObject.getDouble("sellPrice"));
            three.setCreateDate(jsonObject.getLong("createDate"));
            three.setStockId(jsonObject.getInt("stockId"));
            three.setVolumeCode(jsonObject.getStr("volumeCode"));
            threes.add(three);
        }
        return threes;
    }

    public static List<Sell> jsonToTakePosition(String json) {
        JSONArray jsonArray = new JSONArray(json);
        ArrayList<Sell> sells = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Sell sell = new Sell();
            sell.setId(jsonObject.getInt("id"));
            sell.setStockId(jsonObject.getInt("stockId"));
            sell.setSellPrice(jsonObject.getDouble("sellPrice"));
            sell.setUserId(jsonObject.getInt("userId"));
            sell.setCreateDate(jsonObject.getDate("createDate"));
            sell.setNum(jsonObject.getInt("num"));
            sell.setAveragePrice(jsonObject.getDouble("averagePrice"));
            sells.add(sell);
        }
        return sells;
    }

    @PostConstruct
    public void MarketService() {
        System.out.println("mqtt服务端启动");
        Vertx vertx = Vertx.vertx();
        MqttServer mqttServer = MqttServer.create(vertx);
        mqttServer.endpointHandler(endpoint -> {
            // shows main connect info

            // accept connection from the remote client
            endpoint.accept(false);
            endpoint.publishHandler(message -> {
                try {
                    String s = message.payload().toString();
                    System.out.println(s);
//                    TakePosition takePosition = JSONUtil.toBean(s, TakePosition.class);
//                    System.out.println(takePosition);
                    List<Sell> sells = jsonToTakePosition(s);
                    msgList = sells;
                    for (Sell sell : sells) {
                        Order order = toOrder(sell);
                        positionAndThree(order);
                    }

//                   System.out.println(takePositions);

                } catch (Exception e) {
                    System.out.println("receive msg, bug got error.");
                    e.printStackTrace();
                }


            });
        }).listen(1883, "127.0.0.1").onFailure(throwable -> System.out.println("error on start mqtt"));

    }

    @PostConstruct
    public void MarketThreeService() {
        System.out.println("mqtt服务端启动");

        Vertx vertx = Vertx.vertx();
        MqttServer mqttServer = MqttServer.create(vertx);
        mqttServer.endpointHandler(endpoint -> {
            // shows main connect info

            // accept connection from the remote client
            endpoint.accept(false);
            endpoint.publishHandler(message -> {
                try {
                    String s = message.payload().toString();

                    System.out.println(s);
                    List<Three> threes = jsonToThree(s);
//                    System.out.println(threes);
                    sellMsgList = threes;
                    for (Three three : threes) {
                        Order order = toOrder(three);
                        positionAndThree(order);
                        break;
                    }

                    // positionAndThree();
//                    msgList.add(three);
//                    System.out.println("卖出的集合" + objects);
                } catch (Exception e) {
                    System.out.println("receive msg, bug got error.");
                    e.printStackTrace();
                }

            });
        }).listen(1884, "127.0.0.1").onFailure(throwable -> System.out.println("error on start mqtt"));

    }

    private Order toOrder(Sell sell) {
        return new Order(sell.getStockId(), sell.getAveragePrice(), sell.getNum(), Direction.SELL, sell.getNum(),null,sell.getUserId());
    }

    private Order toOrder(Three three) {
        return new Order(three.getStockId(), three.getAveragePrice(), three.getBuyNum(), Direction.BUY, three.getBuyNum(),three.getBuyId(),null);
    }
    @Autowired
    private TakePositionService takePositionService;
    public void positionAndThree(Order order) {
        System.out.println(order);
        OrderBook orderBook = stocks.get(order.getStockId());

        if (orderBook == null) {
            orderBook = new OrderBook();
            orderBook.setStockId(order.getStockId());
            if (order.getType().equals(Direction.BUY)) {
                List<Order> buy = new ArrayList<>();
                buy.add(order);
                orderBook.setBuy(buy);
            }
            if (order.getType() == Direction.SELL) {
                List<Order> sell = new ArrayList<>();
                sell.add(order);
                orderBook.setSell(sell);
            }

            stocks.put(order.getStockId(), orderBook);
        } else {
            System.out.println(orderBook);
            List<Order> orders = order.getType().equals(Direction.BUY) ? orderBook.getSell() : orderBook.getBuy();
            List<Order> priceOk = filterFitPrice(order, orders);
            System.out.println("价格符合条件的：" + priceOk);
            List<Order> finished = new LinkedList<>();
            for (Order o : priceOk) {
                int left = order.getLeft() - o.getLeft();
                if (left > 0) { // order还有剩余数量
                    if(order.getType().equals(Direction.BUY)){
                        TakePosition takePosition = takePositionService.getByStockId(order.getStockId(), o.getSellUserId());
                        if(takePosition!=null){
                            takePositionService.removeById(takePosition.getId());
                            TakePosition takePositionDB = new TakePosition();
                            takePositionDB.setNum(o.getLeft());
                            takePositionDB.setStockId(order.getStockId());
                            takePositionDB.setUserId(order.getBuyUserId());
                            takePositionDB.setVolumeCode(IdUtil.getSnowflake().nextIdStr());
                            takePositionDB.setAveragePrice(new BigDecimal(order.getPrice()));
                            takePositionDB.setVolumePrice(new BigDecimal(order.getPrice()*order.getLeft()));
                            takePositionService.save(takePositionDB);
                        }
                    }else {
                        TakePosition takePositionDB = new TakePosition();
                        takePositionDB.setNum(o.getLeft());
                        takePositionDB.setStockId(order.getStockId());
                        takePositionDB.setUserId(o.getSellUserId());
                        takePositionDB.setVolumeCode(IdUtil.getSnowflake().nextIdStr());
                        takePositionDB.setAveragePrice(new BigDecimal(order.getPrice()));
                        takePositionService.save(takePositionDB);
                    }

                    order.setLeft(left);
                    o.setLeft(0);
                    finished.add(o);
                    System.out.println("order还有剩余数量");
                    break;
                } else if (left < 0) { //order数量消耗完 ， o还有剩余
                    System.out.println("ooooooooo"+o);
                    System.out.println("order==========="+order);
                    if(order.getType().equals(Direction.BUY)){
                        TakePosition takePosition = takePositionService.getByStockId(order.getStockId(), o.getSellUserId());
                        if(takePosition!=null){
                            System.out.println("lllllllllllllll"+order);
                            takePosition.setNum(o.getLeft()-order.getLeft());
                            takePositionService.updateById(takePosition);
                            TakePosition takePositionDB = new TakePosition();
                            takePositionDB.setNum(order.getLeft());
                            takePositionDB.setStockId(order.getStockId());
                            takePositionDB.setUserId(order.getBuyUserId());
                            takePositionDB.setVolumeCode(IdUtil.getSnowflake().nextIdStr());
                            takePositionDB.setAveragePrice(new BigDecimal(order.getPrice()));
                            takePositionDB.setCreateDate(new Date());
                            takePositionDB.setVolumePrice(new BigDecimal(order.getPrice()*order.getLeft()));
                            takePositionService.save(takePositionDB);
                        }
                    }else {
                        TakePosition takePositionDB = new TakePosition();
                        takePositionDB.setNum(order.getLeft());
                        takePositionDB.setStockId(order.getStockId());
                        takePositionDB.setUserId(o.getSellUserId());
                        takePositionDB.setVolumeCode(IdUtil.getSnowflake().nextIdStr());
                        takePositionDB.setAveragePrice(new BigDecimal(order.getPrice()));
                        takePositionService.save(takePositionDB);
                    }
                    o.setLeft(o.getLeft() - order.getLeft());
                    order.setLeft(0);
                    System.out.println("order数量消耗完 ， o还有剩余");
                    break;
                } else { //left =0 表示order 和 o 都消耗完。
                    if(order.getType().equals(Direction.BUY)){
                        TakePosition takePosition = takePositionService.getByStockId(order.getStockId(), o.getSellUserId());
                        if(takePosition!=null){
                            takePosition.setUserId(order.getBuyUserId());
                            //修改价格
                            takePosition.setAveragePrice(new BigDecimal(order.getPrice()));
                            takePosition.setVolumePrice(new BigDecimal(order.getPrice()*order.getLeft()));
                            takePositionService.updateById(takePosition);
                        }
                    }else {
                        TakePosition takePositionDB = new TakePosition();
                        takePositionDB.setNum(order.getLeft());
                        takePositionDB.setStockId(order.getStockId());
                        takePositionDB.setUserId(o.getSellUserId());
                        takePositionDB.setVolumeCode(IdUtil.getSnowflake().nextIdStr());
                        takePositionDB.setAveragePrice(new BigDecimal(order.getPrice()));
                        takePositionService.save(takePositionDB);
                    }
                    order.setLeft(0);
                    o.setLeft(0);
                    finished.add(o);
                    System.out.println("left =0 表示order 和 o 都消耗完。");
                    break;
                }
            }
        }

    }

    public List<Order> filterFitPrice(Order order, List<Order> orders) {
        List<Order> priceOk;
        if (order.getType().equals(Direction.BUY)) {
            priceOk = orders.stream().filter(o -> o.getPrice() <= order.getPrice()).collect(Collectors.toList());
        } else {
            priceOk = orders.stream().filter(o -> o.getPrice() >= order.getPrice()).collect(Collectors.toList());
        }
        return priceOk;
    }

    //public void positionAndThree() {
//    // 将 msgList 转换为 Map，键为 stockId，值为 Message 对象
//    Map<Integer, TakePosition> msgMap = new HashMap<>();
//    for (TakePosition msg : msgList) {
//        msgMap.put(msg.getStockId(), msg);
//    }
//
//    // 遍历 sellMsgList
//    for (Three sellMsg : sellMsgList) {
//        Integer stockId = sellMsg.getStockId();
//
//        // 如果 msgMap 中存在相同 stockId 的 Message 对象
//        if (msgMap.containsKey(stockId)) {
//            TakePosition msg = msgMap.get(stockId);
//
//            // 进行条件判断和相应处理
//            if (msg.getNum() >= sellMsg.getBuyNum() && msg.getSellPrice().compareTo(sellMsg.getSellPrice()) <= 0) {
//                msg.setNum(msg.getNum() - sellMsg.getBuyNum());
//                System.out.println("1===" + msg.getNum());
//
//                // 撮合逻辑...
//                System.out.println("2===" + msg.getNum());
//
//                // TradeOrder 创建及 TCPClient 调用...
//                TradeOrder tradeOrder = new TradeOrder();
//                tradeOrder.setBuyId(sellMsg.getBuyId());
//                tradeOrder.setSellId(sellMsg.getSellId());
//                tradeOrder.setStockId(msg.getStockId());
//                int num = msg.getXvnum() - sellMsg.getBuyNum();
//                BigDecimal bigDecimal = new BigDecimal(num);
//                System.out.println("3===" + num);
//                tradeOrder.setPrice(new BigDecimal(sellMsg.getSellPrice()));
//                tradeOrder.setBuyNum(msg.getNum());
//                tradeOrder.setSellNum(sellMsg.getBuyNum());
//                TCPClient(tradeOrder);
//                System.out.println(sellMsg.getBuyNum());
//
//                if (msg.getNum() <= 0) {
//                    msgMap.remove(stockId);
//                }
//
//                if ((sellMsg.getBuyNum() - num) == 0) {
//                    msgMap.remove(stockId);
//                }
//
//                System.out.println("撮合成功");
//            }
//        }
//    }
//}
//
    public void TCPClient(TradeOrder tradeOrder) {
        Vertx vertx = Vertx.vertx();

        NetClientOptions options = new NetClientOptions()
                .setConnectTimeout(10000)
                .setReconnectAttempts(10)
                .setReconnectInterval(500)
                .setLogActivity(true);
        String s = JSONUtil.toJsonStr(tradeOrder);
        NetClient client = vertx.createNetClient(options);
        client.connect(8896, "127.0.0.1", res -> {
            if (res.succeeded()) {
                System.out.println("连接成功");
                NetSocket socket = res.result();
                try {

                    int length = s.length();
                    System.out.println(length);
                    Buffer buffer = Buffer.buffer().appendInt(length).appendString(s);
                    socket.write(buffer);
                    System.out.println("发送成功");
                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {
                System.out.println("连接失败");
            }
        });

    }
}
